/*

 * Copyright (C) 2008 Universidade Federal de Campina Grande
 *  
 * This file is part of OurGrid. 
 *
 * OurGrid is free software: you can redistribute it and/or modify it under the
 * terms of the GNU Lesser General Public License as published by the Free 
 * Software Foundation, either version 3 of the License, or (at your option) 
 * any later version. 
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details. 
 * 
 * You should have received a copy of the GNU Lesser General Public License 
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * 
 */
package org.ourgrid.common.spec.worker;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.ourgrid.common.spec.OurGridSpec;
import org.ourgrid.worker.WorkerConstants;

/**
 * Entity that encapsulates all the information given by the user about a Worker
 * To provide the information, the user uses the Description Files that can be
 * compiled by CommonCompiler.
 */
public class WorkerSpec extends OurGridSpec implements WorkerSpecConstantes{

	private static final long serialVersionUID = 40L;

	public static final String ATT_TYPE = "type";

	public static final String ATT_PLAYPEN_ROOT = "playpenroot";

	public static final String ATT_PLAYPEN_SIZE = "playpensize";

	public static final String ATT_STORAGE_DIR = "storagedir";

	public static final String ATT_STORAGE_SIZE = "storagesize";

	public static final String ATT_OS = "os";

	public static final String ATT_PROCESSOR_FAMILY = "processorfamily";

	public static final String ATT_MEM = "mem";

	public static final String ATT_BOGO_MIPS = "bogomips";

	public static final String ATT_DEBUG = "debug";

	public static final String ATT_SITE = "site";

	public static final String ATT_STORAGE_SHARED = "storageshared";

	public static final String ATT_ENVIRONMENT = "environment";

	public static final String OS_LINUX = "linux";

	public static final String OS_WINDOWS = "windows";

	public static final String OS_HPUX = "hpux";

	public static final String OS_SOLARIS = "solaris";

	public static final String OS_LINUX_XEN = "/proc/xen";

	public static final String ATT_REM_EXEC = "remExec";

	public static final String ATT_COPY_FROM = "copyFrom";

	public static final String ATT_COPY_TO = "copyTo";

	/** Used on deployment, contains the machine host name */
	public static final String ATT_MACHINE = "machine";

	/**
	 * Used on deployment only, contains the user password for this worker. This
	 * attribute is removed by the peer on 'setworkers'
	 */
	public static final String ATT_PASSWORD = "password";

	/**
	 * An identification of the worker's provider peer in the form "user@server"
	 */
	public static final String ATT_PROVIDER_PEER = "provider";


	/**
	 * Pairs of attribute=value provided by the users.
	 */
	protected Map<String,String> annotations;
	
	public WorkerSpec() {
		this( new LinkedHashMap<String, String>( ) );
	}


	public WorkerSpec( Map<String,String> attributes ) {
		this(attributes, new LinkedHashMap<String, String>( ));	
	}

	public WorkerSpec( Map< String, String > attributes, Map< String, String > annotations ) {
		super( attributes );
		this.annotations = annotations;		
	}


	/**
	 * Returns the value of an annotation given its attribute name.
	 * 
	 * @param attName the attribute name.
	 * @return the attribute value.
	 */
	public String getAnnotation( String attName ) {

		String value = this.annotations.get( attName );
		if ( value != null ) {
			return value;
		}
		return null;
	}

	/**
	 * Sets the annotations collection.
	 * 
	 * @param annotations annotations specified by pairs attribute=value.
	 */
	public void setAnnotations( Map<String, String> annotations ) {

		this.annotations = annotations;
	}

	/**
	 * Adds an annotations collection.
	 * 
	 * @param annotations annotations specified by pairs attribute=value.
	 */
	public void addAllAnnotations( Map<String, String> annotations ) {

		this.annotations.putAll(annotations);
	}
	
	/**
	 * Retrieves the map of annotations.
	 * 
	 * @return a map with all the attributes of this grid machine indexed by the
	 *         name of the attribute.
	 */
	public Map<String,String> getAnnotations() {

		return this.annotations;
	}
	
	@Override
	public String getModuleName() {

		return WorkerConstants.MODULE_NAME;
	}


	@Override
	public String getObjectName() {

		return WorkerConstants.LOCAL_WORKER_MANAGEMENT;
	}


	@Override
	public boolean isValid() {

		return super.isValid();
	}
	
	
	@Override
	public int hashCode(){
		final int PRIME = 31;
		int result = super.hashCode();
		result = PRIME * result + ((this.annotations == null) ? 0 : this.annotations.hashCode());
		return result;
	}
	
	
	@Override
	public String toString(){
		StringBuffer s = new StringBuffer(super.toString());
		
		s.append( "Annotations: " + this.annotations.size() ).append( " \t" );
		
		for (Entry<String,String> entry : this.annotations.entrySet()) {
			//s.append( entry.getKey() ).append( " : " ).append( entry.getValue() ).append( System.getProperty("line.separator") );
			s.append( entry.getKey() ).append( " : " ).append( entry.getValue() ).append( "; \t" );
		}
		s.append( System.getProperty("line.separator") );
		
		return s.toString();
	}
	
	@Override
	public boolean equals(Object obj){
		
		if( !super.equals(obj))
			return false;

		if ( !(obj instanceof WorkerSpec) )
			return false;

		final WorkerSpec other = (WorkerSpec) obj;
		return this.annotations.equals( other.annotations );						
	}


	public void addAnnotation( String property, String value ) {
		this.annotations.put( property, value );
	}
}
